#include "fsxdatadefinitionshelper.h"
using namespace FsxSimConnect;

// Request ids as integers, this is the current request id counter
int FSXDataDefinitionsHelper::_requestAircraftPositionAndSpeedData = (int)RequestAircraftPositionAndSpeedData;
int FSXDataDefinitionsHelper::_requestAircraftStringAndMiscData = (int)RequestAircraftStringAndMiscData;
int FSXDataDefinitionsHelper::_requestAircraftInstrumentationData = (int)RequestAircraftInstrumentationData;
int FSXDataDefinitionsHelper::_requestAircraftAvionicsData = (int)RequestAircraftAvionicsData;

//
// Init minimal Aircraft data
//
int FSXDataDefinitionsHelper::initFSXAircraftMinimal(const HANDLE hSimConnect)
{
    // for some reasons using SIMCONNECT_DATATYPE_STRINGV for the variable strings
    // does not work
    int failures = 0;
    qRegisterMetaType<FSXAircraftMinimal>("FSXAircraftMinimal");
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftMinimal, "ATC TYPE", NULL, SIMCONNECT_DATATYPE_STRING32)) failures++;
    return failures;
}

//
// Init Aircraft string data
// GPS WP PREV | NEXT ID wrong spelling in the docu with underscore
//
int FSXDataDefinitionsHelper::initFSXAircraftStringAndMiscData(const HANDLE hSimConnect)
{
    // for some reasons using SIMCONNECT_DATATYPE_STRINGV for the variable strings
    // does not work
    int failures = 0;
    qRegisterMetaType<FSXAircraftStringAndMiscData>("FSXAircraftStringData");
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftStringAndMiscData, "ATC TYPE", NULL, SIMCONNECT_DATATYPE_STRING32)) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftStringAndMiscData, "ATC MODEL", NULL, SIMCONNECT_DATATYPE_STRING32)) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftStringAndMiscData, "ATC ID", NULL, SIMCONNECT_DATATYPE_STRING32)) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftStringAndMiscData, "ATC AIRLINE", NULL, SIMCONNECT_DATATYPE_STRING64)) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftStringAndMiscData, "ATC FLIGHT NUMBER", NULL, SIMCONNECT_DATATYPE_STRING8)) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftStringAndMiscData, "HSI STATION IDENT", NULL, SIMCONNECT_DATATYPE_STRING8)) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftStringAndMiscData, "TITLE", NULL, SIMCONNECT_DATATYPE_STRING256)) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftStringAndMiscData, "CATEGORY", NULL, SIMCONNECT_DATATYPE_STRING32)) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftStringAndMiscData, "GPS WP PREV ID", NULL, SIMCONNECT_DATATYPE_STRING32)) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftStringAndMiscData, "GPS WP NEXT ID", NULL, SIMCONNECT_DATATYPE_STRING32)) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftStringAndMiscData, "GPS APPROACH AIRPORT ID", NULL, SIMCONNECT_DATATYPE_STRING32)) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftStringAndMiscData, "GPS APPROACH APPROACH ID", NULL, SIMCONNECT_DATATYPE_STRING32)) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftStringAndMiscData, "GPS APPROACH TRANSITION ID", NULL, SIMCONNECT_DATATYPE_STRING32)) failures++;
    return failures;
}

//
// Init position and speed
//
int FSXDataDefinitionsHelper::initFSXAircraftPositionAndSpeedData(const HANDLE hSimConnect) {
    int failures = 0;
    qRegisterMetaType<FSXAircraftPositionAndSpeedData>("FSXAircraftPositionAndSpeedData");
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftPositionAndSpeedData, "GROUND VELOCITY", "knots")) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftPositionAndSpeedData, "TOTAL WORLD VELOCITY", "feet/second")) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftPositionAndSpeedData, "VELOCITY BODY Z", "feet/second")) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftPositionAndSpeedData, "VELOCITY BODY X", "feet/second")) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftPositionAndSpeedData, "VELOCITY BODY Y", "feet/second")) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftPositionAndSpeedData, "VELOCITY WORLD Z", "feet/second")) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftPositionAndSpeedData, "VELOCITY WORLD X", "feet/second")) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftPositionAndSpeedData, "VELOCITY WORLD Y", "feet/second")) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftPositionAndSpeedData, "ACCELERATION BODY Z", "feet per second squared")) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftPositionAndSpeedData, "ACCELERATION BODY X", "feet per second squared")) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftPositionAndSpeedData, "ACCELERATION BODY Y", "feet per second squared")) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftPositionAndSpeedData, "ACCELERATION WORLD Z", "feet per second squared")) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftPositionAndSpeedData, "ACCELERATION WORLD X", "feet per second squared")) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftPositionAndSpeedData, "ACCELERATION WORLD Y", "feet per second squared")) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftPositionAndSpeedData, "ROTATION VELOCITY BODY Z", "feet/second")) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftPositionAndSpeedData, "ROTATION VELOCITY BODY X", "feet/second")) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftPositionAndSpeedData, "ROTATION VELOCITY BODY Y", "feet/second")) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftPositionAndSpeedData, "RELATIVE WIND VELOCITY BODY Z", "feet/second")) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftPositionAndSpeedData, "RELATIVE WIND VELOCITY BODY X", "feet/second")) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftPositionAndSpeedData, "RELATIVE WIND VELOCITY BODY Y", "feet/second")) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftPositionAndSpeedData, "PLANE ALTITUDE", "feet")) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftPositionAndSpeedData, "PLANE ALT ABOVE GROUND", "feet")) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftPositionAndSpeedData, "GROUND ALTITUDE", "meters")) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftPositionAndSpeedData, "PLANE LATITUDE", "radians")) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftPositionAndSpeedData, "PLANE LONGITUDE", "radians")) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftPositionAndSpeedData, "PLANE PITCH DEGREES", "radians")) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftPositionAndSpeedData, "PLANE BANK DEGREES", "radians")) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftPositionAndSpeedData, "PLANE HEADING DEGREES TRUE", "radians")) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftPositionAndSpeedData, "PLANE HEADING DEGREES MAGNETIC", "radians")) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftPositionAndSpeedData, "MAGVAR", "degrees")) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftPositionAndSpeedData, "SURFACE TYPE", NULL)) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftPositionAndSpeedData, "SIM ON GROUND", "bool")) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftPositionAndSpeedData, "INCIDENCE ALPHA", "radians")) failures++; // Angle of attack
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftPositionAndSpeedData, "INCIDENCE BETA", "radians")) failures++;  // Sideslip angle
    return failures;
}

//
// Init instrumentation data
//
int FSXDataDefinitionsHelper::initFSXAircraftInstrumentationData(const HANDLE hSimConnect) {
    int failures = 0;
    qRegisterMetaType<FSXAircraftInstrumentationData>("FSXAircraftInstrumentationData");
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftInstrumentationData, "AIRSPEED TRUE", "knots")) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftInstrumentationData, "AIRSPEED INDICATED", "knots")) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftInstrumentationData, "AIRSPEED TRUE CALIBRATE", "degrees")) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftInstrumentationData, "AIRSPEED BARBER POLE", "knots")) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftInstrumentationData, "AIRSPEED MACH", "mach")) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftInstrumentationData, "VERTICAL SPEED", "feet/second")) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftInstrumentationData, "MACH MAX OPERATE", "mach")) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftInstrumentationData, "OVERSPEED WARNING", NULL)) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftInstrumentationData, "BARBER POLE MACH", "mach")) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftInstrumentationData, "INDICATED ALTITUDE", "feet")) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftInstrumentationData, "KOHLSMAN SETTING MB", "millibars")) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftInstrumentationData, "KOHLSMAN SETTING HG", "inhg")) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftInstrumentationData, "ATTITUDE INDICATOR PITCH DEGREES", "radians")) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftInstrumentationData, "ATTITUDE INDICATOR BANK DEGREES", "radians")) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftInstrumentationData, "ATTITUDE BARS POSITION", "percent over 100")) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftInstrumentationData, "ANGLE OF ATTACK INDICATOR", "radians")) failures++;
    return failures;
}

//
// Init avionics data
//
int FSXDataDefinitionsHelper::initFSXAircraftAvionicsData(const HANDLE hSimConnect)
{
    int failures = 0;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftAvionicsData, "TRANSPONDER CODE:1", NULL)) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftAvionicsData, "TRANSPONDER AVAILABLE", "Bool")) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftAvionicsData, "NAV ACTIVE FREQUENCY:1", "MHz")) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftAvionicsData, "NAV ACTIVE FREQUENCY:2", "MHz")) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftAvionicsData, "COM ACTIVE FREQUENCY:1", "MHz")) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftAvionicsData, "COM ACTIVE FREQUENCY:2", "MHz")) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftAvionicsData, "ADF ACTIVE FREQUENCY:1", "kHz")) failures++;
    if(S_OK != SimConnect_AddToDataDefinition(hSimConnect, DataDefinitionAircraftAvionicsData, "ADF ACTIVE FREQUENCY:2", "kHz")) failures++;
    return failures;
}

//
// Init all
//
int FSXDataDefinitionsHelper::init(const HANDLE hSimConnect)
{
    int failures = 0;
    failures += FSXDataDefinitionsHelper::initFSXAircraftMinimal(hSimConnect);
    failures += FSXDataDefinitionsHelper::initFSXAircraftStringAndMiscData(hSimConnect);
    failures += FSXDataDefinitionsHelper::initFSXAircraftPositionAndSpeedData(hSimConnect);
    failures += FSXDataDefinitionsHelper::initFSXAircraftInstrumentationData(hSimConnect);
    failures += FSXDataDefinitionsHelper::initFSXAircraftAvionicsData(hSimConnect);
    return failures;
}

//
// Get a unique request id withina given range.
//
SIMCONNECT_DATA_REQUEST_ID FSXDataDefinitionsHelper::getRequestId(FSXDataDefinitionsHelper::Requests requestType)
{
    SIMCONNECT_DATA_REQUEST_ID id = 0;
    switch (requestType) {
    case RequestAircraftMinimal:
    {
        id = (SIMCONNECT_DATA_REQUEST_ID)RequestAircraftMinimal;
        break;
    }
    case RequestAircraftStringAndMiscData:
    {
        id = (SIMCONNECT_DATA_REQUEST_ID)FSXDataDefinitionsHelper::_requestAircraftStringAndMiscData++;
        if ((FSXDataDefinitionsHelper::_requestAircraftStringAndMiscData - (int)RequestAircraftStringAndMiscData) >= FSXDataDefinitionsHelper::RequestAircraftStringAndMiscDataRange )
            FSXDataDefinitionsHelper::_requestAircraftStringAndMiscData = (int)RequestAircraftStringAndMiscData;
        break;
    }
    case RequestAircraftPositionAndSpeedData:
    {
        id = (SIMCONNECT_DATA_REQUEST_ID)FSXDataDefinitionsHelper::_requestAircraftPositionAndSpeedData++;
        if ((FSXDataDefinitionsHelper::_requestAircraftPositionAndSpeedData - (int)RequestAircraftPositionAndSpeedData) >= FSXDataDefinitionsHelper::RequestAircraftPositionAndSpeedDataRange )
            FSXDataDefinitionsHelper::_requestAircraftPositionAndSpeedData = (int)RequestAircraftPositionAndSpeedData;
        break;
    }
    case RequestAircraftInstrumentationData:
    {
        id = (SIMCONNECT_DATA_REQUEST_ID)FSXDataDefinitionsHelper::_requestAircraftInstrumentationData++;
        if ((FSXDataDefinitionsHelper::_requestAircraftInstrumentationData - (int)RequestAircraftInstrumentationData) >= FSXDataDefinitionsHelper::RequestAircraftInstrumentationData )
            FSXDataDefinitionsHelper::_requestAircraftInstrumentationData = (int)RequestAircraftInstrumentationData;
        break;
    }
    case RequestAircraftAvionicsData:
    {
        id = (SIMCONNECT_DATA_REQUEST_ID)FSXDataDefinitionsHelper::_requestAircraftAvionicsData++;
        if ((FSXDataDefinitionsHelper::_requestAircraftAvionicsData - (int)RequestAircraftAvionicsData) >= FSXDataDefinitionsHelper::RequestAircraftAvionicsData )
            FSXDataDefinitionsHelper::_requestAircraftAvionicsData = (int)RequestAircraftAvionicsData;
        break;
    }
    }
    return id;
}

//
// Convert the individual id (as per request) back to the base type
//
FSXDataDefinitionsHelper::Requests FSXDataDefinitionsHelper::getBaseRequestId(SIMCONNECT_DATA_REQUEST_ID individualId) {
    int id = (int)individualId;
    if (id == (int )RequestAircraftMinimal) return RequestAircraftMinimal;

    // ranges
    if (id >= (int)RequestAircraftPositionAndSpeedData && id <=((int)RequestAircraftPositionAndSpeedData + FSXDataDefinitionsHelper::RequestAircraftPositionAndSpeedDataRange))
        return  RequestAircraftPositionAndSpeedData;
    if (id >= (int)RequestAircraftStringAndMiscData && id <=((int)RequestAircraftStringAndMiscData + FSXDataDefinitionsHelper::RequestAircraftStringAndMiscDataRange))
        return  RequestAircraftStringAndMiscData;
    if (id >= (int)RequestAircraftInstrumentationData && id <=((int)RequestAircraftInstrumentationData + FSXDataDefinitionsHelper::RequestAircraftInstrumentationDataRange))
        return  RequestAircraftInstrumentationData;
    if (id >= (int)RequestAircraftAvionicsData && id <=((int)RequestAircraftAvionicsData + FSXDataDefinitionsHelper::RequestAircraftAvionicsDataRange))
        return  RequestAircraftAvionicsData;

    // should never get here
    return RequestDefinitionEndMarker;
}
